package cc.bluemc.modules.weixin.action;

import cc.bluemc.modules.weixin.entity.WxPublicAccountEntity;
import cc.bluemc.modules.weixin.service.WxPublicAccountService;
import cc.bluemc.platform.comm.BaseAction;
import cc.bluemc.platform.exception.ServiceException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gson.WeChat;
import com.gson.bean.AuthorizationInfo;
import com.gson.bean.EncryptInMessage;
import com.gson.bean.UserInfo;
import com.gson.bean.WeixinAccount;
import com.gson.oauth.Authorize3p;
import com.gson.oauth.User;
import com.gson.util.*;
import com.thoughtworks.xstream.XStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Company 陕西识代运筹信息科技股份有限公司
 * @Discription
 * @Author houfengli
 * @CreateDate 2017/2/16 9:31
 * @Version 1.0
 */
@Controller
@RequestMapping(value="/wx3p/receive")
public class Weixin3pReceive extends BaseAction{

    private  WeixinAccount weixinAccount=WeixinAccount.getWeixinAccount();
    WCryptUtil cryptUti=new WCryptUtil(weixinAccount.getToken(),
            weixinAccount.getEncodingAesKey(),
            weixinAccount.getAppId());
    @Autowired
    private RedisTemplate<String,String> redisTemplate;



    @Autowired
    private WxPublicAccountService publicAccountService;

    @Value("#{config.base_url}")
    private String base_path;

    /**
     * 接收第三方平台授权推送事件
     * @param request
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping("auth")
    public String auth(HttpServletRequest request) throws Exception {
        ServletInputStream in = request.getInputStream();
        String xmlMsg =  Tools.inputStream2String(in);

        XStream xs = XStreamFactory.init(false);
        xs.ignoreUnknownElements();
        xs.alias("xml", EncryptInMessage.class);
        EncryptInMessage encryptInMessage = (EncryptInMessage) xs.fromXML(xmlMsg);

        if(StringUtils.isNotBlank(encryptInMessage.getEncrypt())){
            xmlMsg=cryptUti.decrypt(encryptInMessage.getEncrypt());
        }
        log.info("收到微信信息："+xmlMsg);
        WeChat.processing(xmlMsg,null);
        return "success";
    }

    /**
     * 接收第三方平台推送事件
     * @param appId
     * @param request
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping("wechatEnvent/{appid:.+}")
    public String wechatEnvent(@PathVariable("appid") String appId,HttpServletRequest request) throws IOException {
        ServletInputStream in = request.getInputStream();
        String xmlMsg =  Tools.inputStream2String(in);
        XStream xs = XStreamFactory.init(false);
        xs.ignoreUnknownElements();
        xs.alias("xml", EncryptInMessage.class);
        EncryptInMessage encryptInMessage = (EncryptInMessage) xs.fromXML(xmlMsg);
        String xml;
        if(StringUtils.isNotBlank(encryptInMessage.getEncrypt())){
            xmlMsg=cryptUti.decrypt(encryptInMessage.getEncrypt());
            log.info(StringUtils.join("收到微信[",appId,"]事件推送：",xmlMsg));
            xml = WeChat.processing(xmlMsg,appId);
            log.info(StringUtils.join("回复[",appId,"]事件推送：",xml));
            xml=cryptUti.encrypt(xmlMsg);
        }else{
            xml = WeChat.processing(xmlMsg,appId);
        }
        if(StringUtils.isBlank(xml)){
            xml="success";
        }
        return xml;
    }

    /**
     * 微信页面授权获取code URL方法
     * @param appId
     * @param redirectUri
     * @return
     */
    @RequestMapping("webAuth/{appid:.+}")
    public String webAuth(@PathVariable("appid") String appId,
                          @RequestParam(required = true)String redirectUri){
        String codeUrl = null;
        try {
            WxPublicAccountEntity accountEntity = publicAccountService.get(appId);
            if(null!=accountEntity){
                long timeMillis = System.currentTimeMillis();
                String chcheKey=StringUtils.join(appId,":",timeMillis);
                redirectUri=URLEncoder.encode(redirectUri, "utf-8");
                BoundValueOperations<String, String> ops = redisTemplate.boundValueOps(chcheKey);
                ops.set(redirectUri);
                ops.expire(10, TimeUnit.MINUTES);

                String baseUrl=StringUtils.join(base_path,"/wx3p/receive/webAuth/callback");
                codeUrl=WeChat.oauth.getCode(appId,URLEncoder.encode(baseUrl, "utf-8"),
                        String.valueOf(timeMillis), weixinAccount.getAppId());
            }else{
                throw new ServiceException("微信页面授权：未授权，appId:"+appId);
            }

        } catch (Exception e) {
            log.error("微信页面授权",e);
        }
        log.info("页面授权，redirectURL："+codeUrl);
        return "redirect:" + codeUrl;
    }
    @RequestMapping("webAuth/callback")
    public String webAuthCallback(@RequestParam(required = true)String code,
                                  @RequestParam(required = true)String appid,
                                  String state) throws UnsupportedEncodingException {

        log.info(StringUtils.join("页面授权回调,code:",code," state:",state," appid:"+appid));
        String chcheKey=StringUtils.join(appid, ":", state);
        BoundValueOperations<String, String> ops = redisTemplate.boundValueOps(chcheKey);
        String cacheRedirectUri=ops.get();

        try {
            String token = WeChat.oauth.getToken(appid, code, weixinAccount.getAppId(),
                    Authorize3p.getComponentToken(weixinAccount));
            JSONObject jsonObject = JSON.parseObject(token);

            cacheRedirectUri=URLDecoder.decode(cacheRedirectUri,"utf-8");
            cacheRedirectUri=StringUtils.join(cacheRedirectUri,
                    cacheRedirectUri.contains("?") ? '&' : '?',
                    "openid=",
                    jsonObject.getString("openid"),
                    "&unionid=",
                    jsonObject.getString("unionid"));
            log.info(appid+"--rectUri:"+cacheRedirectUri);
            return "redirect:" + cacheRedirectUri;
        } catch (Exception e) {
            log.error("微信授权页面回调获取用户openId异常",e);
            return  null;
        }

    }

    /**
     * 测试回调最终显示页面
     * @param id
     * @param map
     * @return
     */
    @RequestMapping("webAuth/webAhthTest")
    public String webAhthTest(String openid,String unionid,String id,ModelMap map){
        log.info(id+"路回来了吧："+openid);
        map.put("userInfo",openid+"&"+unionid);
        return "weixin/webAuthTest";
    }

    /**
     * 公众号[",appid,"]获取[",openid,"]用户信息
     * @param appid
     * @param openid
     * @return
     */
    @ResponseBody
    @RequestMapping("{appid:.+}/getUserInfo/{openid:.+}")
    public UserInfo getUserInfo(@PathVariable("appid") String appid,
                                @PathVariable("openid") String openid){
        try {
            WxPublicAccountEntity accountEntity = publicAccountService.get(appid);
            AuthorizationInfo accessToken =
                    Authorize3p.getAuthAccessToken(weixinAccount, accountEntity.getAppid(),
                            accountEntity.getAuthorizerRefreshToken());

            UserInfo userInfo = User.getUserInfo(accessToken.getAuthorizer_access_token(), openid);
            return userInfo;
        } catch (Exception e) {
            log.error(StringUtils.join("公众号[",appid,"]获取[",openid,"]用户信息异常"),e);
            return null;
        }

    }


    @ResponseBody
    @RequestMapping("{appid:.+}/jsOauth")
    public Map jsOauth(@RequestParam(required = true) String url,
                       @PathVariable("appid") String appid) throws Exception {
        WxPublicAccountEntity wxPublicAccountEntity = publicAccountService.get(appid);
        if(null!=wxPublicAccountEntity){
            WeixinAccount weixinAccount = WeixinAccount.getWeixinAccount();
            String jsapiTicket = Authorize3p.getJsapiTicket(weixinAccount, appid, wxPublicAccountEntity.getAuthorizerRefreshToken());
            Map map= Authorize3p.getJsApiSign(jsapiTicket,url);
            map.put("jsApiList", JsApiSign.JSAPI);
            map.put("appId",appid);
            return map;
        }
        return null;
    }
    @RequestMapping("toJsApiTest")
    public String toJsApiTest(){
        return "weixin/jsApiTest";
    }

    @ResponseBody
    @RequestMapping("getJsSign")
    public Map jsApiTest(@RequestParam(required = true) String url) throws Exception {
        String post=  HttpKit.get("http://115.182.90.94/wx3pf/wx3p/receive/wx4284c021b171c0b8/jsOauth?url="
                + URLEncoder.encode(url, "utf-8"));
        JSONObject parse = JSONObject.parseObject(post);
        return  parse;
    }
}
